# -*- coding: utf-8 -*-
"""
告警策略处理模块
负责管理和执行告警策略
"""

import time
import json
from typing import Dict, Any, List, Optional
import pymysql
from pymysql.cursors import DictCursor
from common.logger import get_logger
from common.config import config

logger = get_logger(__name__)


class AlarmStrategy:
    """告警策略类"""
    
    def __init__(self, strategy_data: Dict[str, Any]):
        """
        初始化告警策略
        
        Args:
            strategy_data: 策略数据
        """
        self.id = strategy_data.get('id')
        self.name = strategy_data.get('name', '')
        self.description = strategy_data.get('description', '')
        self.enabled = strategy_data.get('enabled', True)
        self.conditions = strategy_data.get('conditions', {})
        self.actions = strategy_data.get('actions', [])
        self.created_at = strategy_data.get('created_at')
        self.updated_at = strategy_data.get('updated_at')
    
    def is_triggered(self, log_data: Dict[str, Any]) -> bool:
        """
        检查是否触发策略
        
        Args:
            log_data: 日志数据
            
        Returns:
            是否触发
        """
        if not self.enabled:
            return False
        
        try:
            # 检查级别条件
            if 'level' in self.conditions:
                required_levels = self.conditions['level']
                if isinstance(required_levels, str):
                    required_levels = [required_levels]
                
                log_level = log_data.get('level', '').upper()
                if log_level not in [level.upper() for level in required_levels]:
                    return False
            
            # 检查应用条件
            if 'app_name' in self.conditions:
                required_apps = self.conditions['app_name']
                if isinstance(required_apps, str):
                    required_apps = [required_apps]
                
                log_app = log_data.get('app_name', '')
                if log_app not in required_apps:
                    return False
            
            # 检查关键词条件
            if 'keywords' in self.conditions:
                required_keywords = self.conditions['keywords']
                if isinstance(required_keywords, str):
                    required_keywords = [required_keywords]
                
                log_message = log_data.get('message', '').lower()
                if not any(keyword.lower() in log_message for keyword in required_keywords):
                    return False
            
            # 检查正则表达式条件
            if 'regex_patterns' in self.conditions:
                import re
                patterns = self.conditions['regex_patterns']
                if isinstance(patterns, str):
                    patterns = [patterns]
                
                log_message = log_data.get('message', '')
                if not any(re.search(pattern, log_message) for pattern in patterns):
                    return False
            
            # 检查时间条件
            if 'time_range' in self.conditions:
                time_range = self.conditions['time_range']
                current_hour = time.localtime().tm_hour
                
                start_hour = time_range.get('start_hour', 0)
                end_hour = time_range.get('end_hour', 23)
                
                if not (start_hour <= current_hour <= end_hour):
                    return False
            
            # 检查频率限制
            if 'frequency_limit' in self.conditions:
                frequency_limit = self.conditions['frequency_limit']
                # 这里需要实现频率限制逻辑
                # 暂时跳过频率限制检查
                pass
            
            return True
            
        except Exception as e:
            logger.error(f"检查策略触发条件失败: {e}")
            return False
    
    def get_actions(self) -> List[Dict[str, Any]]:
        """
        获取策略动作
        
        Returns:
            动作列表
        """
        return self.actions
    
    def to_dict(self) -> Dict[str, Any]:
        """
        转换为字典
        
        Returns:
            策略字典
        """
        return {
            'id': self.id,
            'name': self.name,
            'description': self.description,
            'enabled': self.enabled,
            'conditions': self.conditions,
            'actions': self.actions,
            'created_at': self.created_at,
            'updated_at': self.updated_at
        }


class AlarmStrategyManager:
    """告警策略管理器"""
    
    def __init__(self):
        """初始化策略管理器"""
        self.mysql_client = self._create_mysql_client()
        self.strategies_cache = {}
        self.last_cache_update = 0
        self.cache_ttl = 300  # 5分钟缓存
    
    def _create_mysql_client(self) -> pymysql.Connection:
        """
        创建MySQL客户端连接
        
        Returns:
            MySQL连接对象
        """
        mysql_config = config.get('mysql', {})
        
        try:
            connection = pymysql.connect(
                host=mysql_config.get('host', 'localhost'),
                port=mysql_config.get('port', 3306),
                user=mysql_config.get('user', 'root'),
                password=mysql_config.get('password', 'password'),
                database=mysql_config.get('database', 'log_analysis'),
                charset=mysql_config.get('charset', 'utf8mb4'),
                cursorclass=DictCursor,
                autocommit=True
            )
            
            logger.info(f"成功连接到MySQL: {mysql_config.get('host')}:{mysql_config.get('port')}")
            return connection
            
        except Exception as e:
            logger.error(f"连接MySQL失败: {e}")
            raise
    
    def get_all_strategies(self) -> List[AlarmStrategy]:
        """
        获取所有策略
        
        Returns:
            策略列表
        """
        # 检查缓存
        current_time = time.time()
        if current_time - self.last_cache_update < self.cache_ttl and self.strategies_cache:
            return list(self.strategies_cache.values())
        
        try:
            with self.mysql_client.cursor() as cursor:
                sql = """
                SELECT * FROM alarm_strategies 
                WHERE enabled = 1 
                ORDER BY created_at DESC
                """
                cursor.execute(sql)
                strategies_data = cursor.fetchall()
                
                # 更新缓存
                self.strategies_cache.clear()
                strategies = []
                
                for strategy_data in strategies_data:
                    strategy = AlarmStrategy(strategy_data)
                    self.strategies_cache[strategy.id] = strategy
                    strategies.append(strategy)
                
                self.last_cache_update = current_time
                logger.info(f"加载了 {len(strategies)} 个告警策略")
                return strategies
                
        except Exception as e:
            logger.error(f"获取告警策略失败: {e}")
            return []
    
    def get_strategy_by_id(self, strategy_id: int) -> Optional[AlarmStrategy]:
        """
        根据ID获取策略
        
        Args:
            strategy_id: 策略ID
            
        Returns:
            策略对象
        """
        # 先检查缓存
        if strategy_id in self.strategies_cache:
            return self.strategies_cache[strategy_id]
        
        try:
            with self.mysql_client.cursor() as cursor:
                sql = "SELECT * FROM alarm_strategies WHERE id = %s"
                cursor.execute(sql, (strategy_id,))
                strategy_data = cursor.fetchone()
                
                if strategy_data:
                    strategy = AlarmStrategy(strategy_data)
                    self.strategies_cache[strategy_id] = strategy
                    return strategy
                
                return None
                
        except Exception as e:
            logger.error(f"获取策略失败: {e}")
            return None
    
    def create_strategy(self, strategy_data: Dict[str, Any]) -> Optional[int]:
        """
        创建策略
        
        Args:
            strategy_data: 策略数据
            
        Returns:
            策略ID
        """
        try:
            with self.mysql_client.cursor() as cursor:
                sql = """
                INSERT INTO alarm_strategies (
                    name, description, enabled, conditions, actions, created_at, updated_at
                ) VALUES (
                    %s, %s, %s, %s, %s, NOW(), NOW()
                )
                """
                
                values = (
                    strategy_data.get('name'),
                    strategy_data.get('description'),
                    strategy_data.get('enabled', True),
                    json.dumps(strategy_data.get('conditions', {})),
                    json.dumps(strategy_data.get('actions', []))
                )
                
                cursor.execute(sql, values)
                strategy_id = cursor.lastrowid
                
                # 清除缓存
                self.strategies_cache.clear()
                self.last_cache_update = 0
                
                logger.info(f"创建告警策略成功: {strategy_id}")
                return strategy_id
                
        except Exception as e:
            logger.error(f"创建策略失败: {e}")
            return None
    
    def update_strategy(self, strategy_id: int, strategy_data: Dict[str, Any]) -> bool:
        """
        更新策略
        
        Args:
            strategy_id: 策略ID
            strategy_data: 策略数据
            
        Returns:
            是否成功
        """
        try:
            with self.mysql_client.cursor() as cursor:
                sql = """
                UPDATE alarm_strategies SET
                    name = %s, description = %s, enabled = %s, 
                    conditions = %s, actions = %s, updated_at = NOW()
                WHERE id = %s
                """
                
                values = (
                    strategy_data.get('name'),
                    strategy_data.get('description'),
                    strategy_data.get('enabled', True),
                    json.dumps(strategy_data.get('conditions', {})),
                    json.dumps(strategy_data.get('actions', [])),
                    strategy_id
                )
                
                cursor.execute(sql, values)
                
                # 清除缓存
                self.strategies_cache.clear()
                self.last_cache_update = 0
                
                logger.info(f"更新告警策略成功: {strategy_id}")
                return True
                
        except Exception as e:
            logger.error(f"更新策略失败: {e}")
            return False
    
    def delete_strategy(self, strategy_id: int) -> bool:
        """
        删除策略
        
        Args:
            strategy_id: 策略ID
            
        Returns:
            是否成功
        """
        try:
            with self.mysql_client.cursor() as cursor:
                sql = "DELETE FROM alarm_strategies WHERE id = %s"
                cursor.execute(sql, (strategy_id,))
                
                # 清除缓存
                self.strategies_cache.clear()
                self.last_cache_update = 0
                
                logger.info(f"删除告警策略成功: {strategy_id}")
                return True
                
        except Exception as e:
            logger.error(f"删除策略失败: {e}")
            return False
    
    def check_log_against_strategies(self, log_data: Dict[str, Any]) -> List[AlarmStrategy]:
        """
        检查日志是否匹配任何策略
        
        Args:
            log_data: 日志数据
            
        Returns:
            匹配的策略列表
        """
        strategies = self.get_all_strategies()
        matched_strategies = []
        
        for strategy in strategies:
            if strategy.is_triggered(log_data):
                matched_strategies.append(strategy)
        
        return matched_strategies
    
    def get_strategy_stats(self) -> Dict[str, Any]:
        """
        获取策略统计信息
        
        Returns:
            策略统计信息
        """
        try:
            with self.mysql_client.cursor() as cursor:
                # 获取总策略数
                cursor.execute("SELECT COUNT(*) as total FROM alarm_strategies")
                total_count = cursor.fetchone()['total']
                
                # 获取启用策略数
                cursor.execute("SELECT COUNT(*) as enabled FROM alarm_strategies WHERE enabled = 1")
                enabled_count = cursor.fetchone()['enabled']
                
                # 获取禁用策略数
                cursor.execute("SELECT COUNT(*) as disabled FROM alarm_strategies WHERE enabled = 0")
                disabled_count = cursor.fetchone()['disabled']
                
                return {
                    'total_strategies': total_count,
                    'enabled_strategies': enabled_count,
                    'disabled_strategies': disabled_count,
                    'cache_size': len(self.strategies_cache),
                    'last_cache_update': self.last_cache_update
                }
                
        except Exception as e:
            logger.error(f"获取策略统计信息失败: {e}")
            return {}
    
    def clear_cache(self) -> None:
        """清除策略缓存"""
        self.strategies_cache.clear()
        self.last_cache_update = 0
        logger.info("策略缓存已清除")
    
    def close(self):
        """关闭连接"""
        try:
            if self.mysql_client:
                self.mysql_client.close()
            logger.info("策略管理器连接已关闭")
        except Exception as e:
            logger.error(f"关闭连接时发生错误: {e}") 